import json
from google.appengine.ext import ndb
from model_child import Child
from model_parent import Parent
from model_PC import PC

class Kindergarten (ndb.Model):
    """ Models an individual Kindergarten entry with content and id (email address)"""

    CT_first_name =     ndb.StringProperty()
    CT_last_name =      ndb.StringProperty()
    KG_name =        ndb.StringProperty()
    address =       ndb.StringProperty()
    phone_number =   ndb.StringProperty()
    email_address =  ndb.StringProperty()
    KG_id =          ndb.StringProperty()

    def care_taker_name(self):
        return self.CT_first_name + " " + self.CT_last_name

    @staticmethod
    def create_KG_from_json(KG_info_json):
        """ Create and put a new kindergarten in db, make sure caretaker mail address is not exists """
        data = json.loads(KG_info_json)
        kinder = Kindergarten(CT_first_name =   data.get("CT_first_name"),
                              CT_last_name =        data.get("CT_last_name"),
                              KG_name =        data.get("KG_name"),
                              phone_number =          data.get("phone_number"),
                              email_address =     data.get("email_address"),
                              address =         data.get("address"),
                              KG_id =             data.get("email_address"))
        check_kinder_exists = Kindergarten.query(Kindergarten.email_address == data.get("email_address")).get()
        if check_kinder_exists is not None:
            return -1
        return kinder.put()

    @staticmethod
    def update_KG_from_json(KG_info_json):
        """ update kindergarten info, make sure caretaker mail address is exists (and so KG exist) """
        data = json.loads(KG_info_json)
        kinder = Kindergarten(CT_first_name =   data.get("CT_first_name"),
                              CT_last_name =        data.get("CT_last_name"),
                              KG_name =        data.get("KG_name"),
                              phone_number =          data.get("phone_number"),
                              email_address =     data.get("email_address"),
                              address =         data.get("address"),
                              KG_id =             data.get("email_address"))
        check_kinder_exists = Kindergarten.query(Kindergarten.email_address == data.get("email_address")).get()
        if check_kinder_exists is not None:
            check_kinder_exists.key.delete()
            kinder.put()
            return 1
        else:
            return -1

    @staticmethod
    def get_name_KG_CT_by_id(KG_id_given):
        """ Returns name of caretaker and KG name of KG with required ID """
        KG_req = Kindergarten.query(Kindergarten.KG_id == KG_id_given).get()
        if KG_req is None:
            return -1
        details  = {}
        details ['KG_name'] = KG_req.KG_name
        details ['CT_name'] = KG_req.care_taker_name()
        return details

    @staticmethod
    def create_new_entity_from_teacher_by_json(data_json):
        """ Create a new Child, Parent, PC entity from their models by given json """

        # check existence of entity
        if Kindergarten.check_existence_entity(data_json=data_json) == -1:
            return -1
        res_create = Kindergarten.create_new_entity_from_json_after_check_existence(data_json=data_json)
        if res_create != 1:
            return res_create
        return 1

    @staticmethod
    def check_existence_entity(data_json):
        """ check if there is an entity with same values
            return 1 iff it is possible to put an entity with those details """
        data = json.loads(data_json)
        check_child_exists = Child.query(Child.child_id == data.get("child_id")).get()
        if check_child_exists is not None:
            return -1
        check_pc_exists = PC.check_existence_parent_child_entity(data.get("parent1_email_address"), data.get("child_id"))
        if check_pc_exists == 1:
            return -3
        parent2_email_address = data.get("parent2_email_address")
        if parent2_email_address is not None:
            check_pc_exists = PC.check_existence_parent_child_entity(parent2_email_address, data.get("child_id"))
            if check_pc_exists == 1:
                return -5
        return 1

    @staticmethod
    def create_new_entity_from_json_after_check_existence(data_json):
        """ create new child, PC and parents entities after checked by other function that it can be create"""
        data = json.loads(data_json)
        # create child #
        child_info = {"first_name": data.get("child_first_name"),
                  "last_name": data.get("child_last_name"),
                  "child_id": data.get("child_id"),
                  "gender": data.get("gender"),
                  "date_of_birth": data.get("date_of_birth"),
                  "phone_number": data.get("phone_number"),
                  "address": data.get("address" ),
                  "KG_id": data.get("KG_id")}
        child_info_json = json.dumps(child_info)
        res_child = Child.create_child_from_json(child_info_json)
        if(res_child == -1):
            return -2

        # create first parent #
        parent1_info = {"first_name": data.get("parent1_first_name"),
                        "last_name": data.get("parent1_last_name"),
                        "phone_number": data.get("parent1_phone_number"),
                        "email_address": data.get("parent1_email_address")}
        parent1_info_json = json.dumps(parent1_info)
        res_parent1 = Parent.create_parent_from_json(parent1_info_json)
        if (res_parent1 == -1):
            return -3

        # create PC entity
        res_pc1 = PC.create_parent_child_entity(data.get("parent1_email_address"), data.get("child_id"))
        if (res_pc1 == -1):
            return -4

        parent2_email_address = data.get("parent2_email_address")
        if parent2_email_address != "":
            # create second parent #
            parent2_info = {"first_name": data.get("parent2_first_name"),
                            "last_name": data.get("parent2_last_name"),
                            "phone_number": data.get("parent2_phone_number"),
                            "email_address": parent2_email_address}
            parent2_info_json = json.dumps(parent2_info)
            res_parent2 = Parent.create_parent_from_json(parent2_info_json)
            if (res_parent2 == -1):
                return -5

            # create PC entity
            res_pc2 = PC.create_parent_child_entity(data.get("parent2_email_address"), data.get("child_id"))
            if (res_pc2 == -1):
                return -6
        return 1

    @staticmethod
    def update_entity_from_teacher_by_json(data_json):
        """ Create a new Child, Parent, PC entity from their models by given json """
        data = json.loads(data_json)
        # check existence of entity, return -1 if entity doesnt exist
        if Kindergarten.check_existence_entity(data_json=data_json) == 1:
            return -1
        # try to delete all entities from db,
        # if some deletion goes wrong, continue to delete but change the bool var problem to true
        problem = False
        child_id_given = data.get("child_id")
        if Child.delete_child_by_id(child_id_given) == -1: # delete child and PC entities
            problem = True
        if Parent.delete_parent_by_id(data.get("parent1_email_address")) == -1:
            problem = True
        parent2_email_address = data.get("parent2_email_address")
        if parent2_email_address != "":
            if Parent.delete_parent_by_id(parent2_email_address) == -1:
                problem = True
        if problem:
            return -2
        res_create = Kindergarten.create_new_entity_from_json_after_check_existence(data_json=data_json)
        if res_create != 1:
            return res_create
        return 1

    @staticmethod
    def get_KG_info_by_KG_id(data_json):
        """ Returns info about specific kindergarten by his id """
        data = json.loads(data_json)
        given_KG_id = data.get("KG_id")
        KG_req = Kindergarten.query(Kindergarten.KG_id == given_KG_id).get()
        if KG_req is None:
            return -1
        details  = {}
        details ['KG_name'] = KG_req.KG_name
        details ['CT_first_name'] = KG_req.CT_first_name
        details ['CT_last_name'] = KG_req.CT_last_name
        details ['KG_name'] = KG_req.KG_name
        details ['address'] = KG_req.address
        details ['phone_number'] = KG_req.phone_number
        details_json = json.dumps(details)
        return details_json

    @staticmethod
    def get_all_children_info_in_KG(data_json):
        """ return list with info about all children in kindergarten by his id (in json) """
        data = json.loads(data_json)
        given_KG_id = data.get("KG_id")
        childs = ndb.gql("SELECT * FROM Child WHERE KG_id = :teacher", teacher=given_KG_id)
        res = []
        for c in childs:
            data = {"first_name" : c.first_name,
                    "last_name" : c.last_name,
                    "child_id" : c.child_id,
                    "gender" : c.gender,
                    "date_of_birth" : str(c.date_of_birth),
                    "phone_number":  c.phone,
                    "address": c.address
                    }
            data_s = json.dumps(data)
            res.append(data_s)
        return res

    @staticmethod
    def get_all_children_ids_in_KG_by_json(data_json):
        """ return list with id's of all children in kindergarten by his id (in json) """
        data = json.loads(data_json)
        given_KG_id = data.get("KG_id")
        childs = ndb.gql("SELECT * FROM Child WHERE KG_id = :teacher", teacher=given_KG_id)
        res = ""
        for c in childs:
            res += c.child_id + ','
        res = res[:-1]
        return res

    @staticmethod
    def check_existence_KG(given_KG_id):
        """ Return true iff there is a kindergarten with this id """
        k = ndb.gql("SELECT * FROM Kindergarten WHERE KG_id = :teacher", teacher=given_KG_id).fetch()
        return len(k) != 0

    @staticmethod
    def check_existence_children_in_KG(given_KG_id):
        """ Return true iff there are children in kindergarten with given id """
        children = ndb.gql("SELECT * FROM Child WHERE KG_id = :teacher", teacher=given_KG_id).fetch()
        return len(children) != 0